/**
 * Description:等额本金工具类
 * Copyright: Copyright (Corporation)2015
 * Company: Corporation
 * @author: 凯文加内特
 * @version: 1.0
 * Created at: 2015年12月1日 上午8:38:23
 * Modification History:
 * Modified by : 
 */

package luxing.util;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

/**
 * 等额本金是指一种贷款的还款方式，是在还款期内把贷款数总额等分，每月偿还同等数额的本金和剩余贷款在该月所产生的利息，这样由于每月的还款本金额固定，
 * 而利息越来越少，借款人起初还款压力较大，但是随时间的推移每月还款数也越来越少。
 */
public class AverageCapitalUtil {

	/**
	 * 等额本金计算获取还款方式为等额本金的每月偿还本金和利息
	 * 
	 * 公式：每月偿还本金=(贷款本金÷还款月数)+(贷款本金-已归还本金累计额)×月利率
	 * 
	 * @param loanAmount
	 *            总借款额（贷款本金）
	 * @param rate
	 *            月利率
	 * @param period
	 *            还款总月数
	 * @return 每月偿还本金和利息,不四舍五入，直接截取小数点最后两位
	 */
	public static Map<Integer, BigDecimal> getPerMonthPrincipalInterest(BigDecimal loanAmount, BigDecimal rate,
			int period) {
		Map<Integer, BigDecimal> map = new HashMap<Integer, BigDecimal>();
		// 每月本金
		BigDecimal monthPri = getPerMonthPrincipal(loanAmount, period);
		for (int i = 1; i <= period; i++) {
			BigDecimal monthRes = monthPri
					.add((loanAmount.subtract(monthPri.multiply(new BigDecimal(i - 1)))).multiply(rate));
			monthRes = monthRes.setScale(1, BigDecimal.ROUND_DOWN);
			map.put(i, monthRes);
		}
		return map;
	}

	/**
	 * 等额本金计算获取还款方式为等额本金的每月偿还利息
	 * 
	 * 公式：每月应还利息=剩余本金×月利率=(贷款本金-已归还本金累计额)×月利率
	 * 
	 * @param loanAmount
	 *            总借款额（贷款本金）
	 * @param rate
	 *            月利率
	 * @param period
	 *            还款总月数
	 * @return 每月偿还利息
	 */
	public static Map<Integer, BigDecimal> getPerMonthInterest(BigDecimal loanAmount, BigDecimal rate, int period) {
		Map<Integer, BigDecimal> inMap = new HashMap<Integer, BigDecimal>();
		BigDecimal principal = getPerMonthPrincipal(loanAmount, period);
		Map<Integer, BigDecimal> map = getPerMonthPrincipalInterest(loanAmount, rate, period);
		for (Map.Entry<Integer, BigDecimal> entry : map.entrySet()) {
			BigDecimal interestBigDecimal = entry.getValue().subtract(principal);
			interestBigDecimal = interestBigDecimal.setScale(1, BigDecimal.ROUND_DOWN);
			inMap.put(entry.getKey(), interestBigDecimal);
		}
		return inMap;
	}

	/**
	 * 等额本金计算获取还款方式为等额本金的每月偿还本金
	 * 
	 * 公式：每月应还本金=贷款本金÷还款月数
	 * 
	 * @param loanAmount
	 *            总借款额（贷款本金）
	 * @param period
	 *            还款总月数
	 * @return 每月偿还本金
	 */
	public static BigDecimal getPerMonthPrincipal(BigDecimal loanAmount, int period) {
		BigDecimal monthIncome = loanAmount.divide(new BigDecimal(period), 1, BigDecimal.ROUND_DOWN);
		return monthIncome;
	}

	/**
	 * 等额本金计算获取还款方式为等额本金的总利息
	 * 
	 * @param loanAmount
	 *            总借款额（贷款本金）
	 * @param rate
	 *            月利率
	 * @param period
	 *            还款总月数
	 * @return 总利息
	 */
	public static BigDecimal getTotalInterest(BigDecimal loanAmount, BigDecimal rate, int period) {
		BigDecimal count = new BigDecimal(0);
		Map<Integer, BigDecimal> mapInterest = getPerMonthInterest(loanAmount, rate, period);

		for (Map.Entry<Integer, BigDecimal> entry : mapInterest.entrySet()) {
			count = count.add(entry.getValue());
		}
		return count;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		BigDecimal loanAmount = new BigDecimal(10000); // 本金
		int period = 10;
		BigDecimal rate = new BigDecimal(0.01); // 利率
		Map<Integer, BigDecimal> getPerMonthPrincipalInterest = getPerMonthPrincipalInterest(loanAmount, rate, period);
		System.out.println("等额本金---每月本息：" + getPerMonthPrincipalInterest);
		BigDecimal benjin = getPerMonthPrincipal(loanAmount, period);
		System.out.println("等额本金---每月本金:" + benjin);
		Map<Integer, BigDecimal> mapInterest = getPerMonthInterest(loanAmount, rate, period);
		System.out.println("等额本金---每月利息:" + mapInterest);

		BigDecimal count = getTotalInterest(loanAmount, rate, period);
		System.out.println("等额本金---总利息：" + count);
	}
}